package mesh

import (
	"cgs-server/server/base"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"time"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"

	"cgs-server/helper"
	"cgs-server/server"
)

func init() {
	//server.Handle(http.MethodPost, "/api/Mesh/Add", Add, server.AddMesh)
	server.Post("/api/Mesh/Add", Add, "添加模型", server.Login)
	server.Post("/api/mesh/3DTiles/add", add3DTiles, "添加3DTiles", server.Login)
	server.Get("/api/mesh/add-default", addDefaultModel, "添加系统内置模型", server.None)
	//server.Post("/api/mesh/mapbox/add", addQgis2Web, "添加3DTiles", server.Login)
}

// Add upload a mesh.
func Add(w http.ResponseWriter, r *http.Request) {
	// 15 MB
	r.ParseMultipartForm(server.Config.Upload.ModelMaxSize)
	files := r.MultipartForm.File

	// check upload file
	if len(files) != 1 {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Please select an file.",
		})
		return
	}

	file := files["file"][0]
	fileName := file.Filename
	fileSize := file.Size
	fileType := file.Header.Get("Content-Type")
	fileExt := filepath.Ext(fileName)
	fileNameWithoutExt := strings.TrimSuffix(fileName, fileExt)

	if strings.ToLower(fileExt) != ".zip" {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  "Only zip file is allowed!",
		})
		return
	}

	// save file
	now := time.Now()

	savePath := fmt.Sprintf("/Upload/Model/%v", helper.TimeToString(now, "yyyyMMddHHmmss"))
	physicalPath := server.MapPath(savePath)

	tempPath := filepath.Join(physicalPath, "temp")

	if _, err := os.Stat(tempPath); os.IsNotExist(err) {
		os.MkdirAll(tempPath, 0755)
	}

	targetPath := filepath.Join(tempPath, fileName)
	target, err := os.Create(targetPath)
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	defer target.Close()

	source, err := file.Open()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}
	defer source.Close()

	io.Copy(target, source)

	err = helper.UnZip(targetPath, physicalPath)
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}

	//os.RemoveAll(tempPath)  //2020-01-14,这里保留zip文件，以便导出时速度快

	// justify file type
	entryFileName, meshType, err := getMeshType(savePath, targetPath)
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}

	// save to mongo
	pinyin := helper.ConvertToPinYin(fileNameWithoutExt)

	db, err := server.Mongo()
	if err != nil {
		helper.WriteJSON(w, server.Result{
			Code: 300,
			Msg:  err.Error(),
		})
		return
	}

	doc := bson.M{
		"ID":          primitive.NewObjectID(),
		"AddTime":     now,
		"FileName":    fileName,
		"FileSize":    fileSize,
		"FileType":    fileType,
		"FirstPinYin": pinyin.FirstPinYin,
		"Name":        fileNameWithoutExt,
		"SaveName":    fileName,
		"SavePath":    savePath,
		"Thumbnail":   "",
		"TotalPinYin": pinyin.TotalPinYin,
		"Type":        meshType,
		"Url":         entryFileName,
	}

	if server.Config.Authority.Enabled {
		user, _ := server.GetCurrentUser(r)

		if user != nil {
			doc["UserID"] = user.ID
		}
	}

	db.InsertOne(server.MeshCollectionName, doc)

	helper.WriteJSON(w, server.Result{
		Code: 200,
		Msg:  "Upload successfully!",
	})
}

func add3DTiles(w http.ResponseWriter, r *http.Request) {
	name := r.FormValue("name")
	url := r.FormValue("url")

	mesh := &Model{
		Name: name,
		URL:  url,
	}

	dataUserModel := base.GenerateDataUserModel(mesh, r)

	meshService := NewMeshService()
	err := meshService.Add3DTiles(dataUserModel)

	if err != nil {
		_, _ = helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}

	_, _ = helper.WriteJSON(w, server.OK("Add successfully!"))
}

func addDefaultModel(w http.ResponseWriter, r *http.Request) {
	modelPath := r.FormValue("modelPath")
	service := NewMeshService()
	err := service.AddDefaultModels(modelPath)
	if err != nil {
		helper.WriteJSON(w, server.Fail(err.Error()))
		return
	}
	helper.WriteJSON(w, server.OK())
}
